﻿using HAF.LogUtility;
using HAF.LogUtility.Except;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;

namespace SoapNotify.Assistantor
{
    /// <summary>
    /// 工单解析处理
    /// </summary>
    [DisplayName("工单处理")]
    public class XmlAssistant: PushMessageable
    {
        private XmlAssistant() { }

        private static XmlAssistant _xmlObj;

        public static XmlAssistant GetInstance()
        {
            return _xmlObj ?? (_xmlObj = new XmlAssistant());
        }

        /******************************************************
        xsi全名：xml schema instance
        web-app是web.xml的根节点标签名称
        version是版本的意思
        xmlns是web.xml文件用到的命名空间
        xmlns:xsi是指web.xml遵守xml规范
        xsi:schemaLocation是指具体用到的schema资源
        ******************************************************/

        #region 内容工单处理
        /// <summary>
        /// 读取回单内容
        /// </summary>
        /// <param name="xmlContent">回单数据</param>
        /// <returns></returns>
        public string ReadReplyXml(string xmlContent)
        {
            string errContent = string.Empty;
            XDocument rootNode = XDocument.Parse(xmlContent);

            XElement rootElement = rootNode.Root;
            if (rootElement != null && rootElement.HasElements)
            {
                var tt = rootElement.Element("Reply");
                if (tt != null)
                {
                    errContent = tt.Value;
                }
                //foreach (var item in rootElement.Elements())
                //{
                //    //errContent += item.Value;
                //    errContent = item.Value;
                //}
            }
            return errContent;
        }

        /// <summary>
        /// 读取回单内容
        /// </summary>
        /// <param name="xmlContent"></param>
        /// <returns></returns>
        public string ReadReplyContent(string xmlPath, string logName)
        {
            if (string.IsNullOrEmpty(xmlPath))
            {
                LogHelper.WriteErrorLogExt(logName, "输入参数不正确");
                return "";
            }
            LogHelper.WriteDebugLogExt(logName, "开始解析回单内容");
            StringBuilder sbContent = new StringBuilder();
            if (File.Exists(xmlPath))
            {
                XDocument rootNode = XDocument.Load(xmlPath);
                LogHelper.WriteDebugLogExt(logName, "回单文件内容：\r\n {0}", rootNode.Document.ToString());
                var movieNodes = from myTarget in rootNode.Descendants("Property")
                                 where myTarget.Attribute("Name").Value.Equals("Result")
                                 select myTarget;
                //LogHelper.WriteDebugLogExt(logName, "提取数据状态为{0}", movieNodes.Any());
                if (movieNodes.Any())
                {
                    LogHelper.WriteDebugLogExt(logName, "提取到{0}条回执信息", movieNodes.Count());
                    foreach (var item in movieNodes)
                    {
                        //Console.WriteLine(item.Attribute("Name").Value);
                        //Console.WriteLine(item.Value);
                        //LogHelper.WriteDebugLogExt(logName, item.Value);
                        if (!item.Value.Equals("0"))
                        {
                            XNode a = item.NextNode;  //获取同级的下一节点数据
                            //LogHelper.WriteDebugLogExt(logName, ((XElement)a).Value);
                            if (a == null)
                            {
                                a = item.PreviousNode;
                            }
                            if (a != null) sbContent.Append(string.Format("ErrCode:{0} Message:{1} ", item.Value, ((XElement)a).Value));
                        }

                    }
                }
                else
                {
                    ReadReplyXml(rootNode.Document.ToString());
                    LogHelper.WriteErrorLogExt(logName, "未找到回执错误消息");
                }
            }
            return sbContent.ToString();
        }

        /// <summary>
        /// 是否进行视频节点的解析
        /// </summary>
        private bool _isContentNode = true;

        /// <summary>
        /// 读取并输出发布工单内容
        /// </summary>
        /// <param name="xmlInPath"></param>
        /// <param name="xmlOutPath"></param>
        /// <returns></returns>
        public string RenewPubXml(string xmlInPath, string xmlOutPath, string logName = "test")
        {
            try
            {
                WriteInfoMessage(xmlInPath);
                WriteInfoMessage("输入文件 {0}", xmlInPath);
                WriteInfoMessageExt("testlog", xmlOutPath);
                WriteInfoMessageExt("testlog", "输出文件 {0}", xmlOutPath);
                StringBuilder sbContent = new StringBuilder();
                if (File.Exists(xmlInPath))
                {
                    XDocument rootNode = XDocument.Load(xmlInPath);
                    var movieNodes = from myTarget in rootNode.Descendants("Property")
                                     where myTarget.Attribute("Name").Value.Equals("Result")
                                     select myTarget;
                    //LogHelper.WriteDebugLogExt(logName, "提取数据状态为{0}", movieNodes.Any());
                    if (movieNodes.Any())
                    {
                        LogHelper.WriteDebugLogExt(logName, "提取到{0}条回执信息", movieNodes.Count());
                        foreach (var item in movieNodes)
                        {
                            //Console.WriteLine(item.Attribute("Name").Value);
                            //Console.WriteLine(item.Value);
                            //LogHelper.WriteDebugLogExt(logName, item.Value);
                            if (!item.Value.Equals("0"))
                            {
                                XNode a = item.NextNode;  //获取同级的下一节点数据
                                if (a == null)
                                {
                                    a = item.PreviousNode;
                                }
                                //LogHelper.WriteDebugLogExt(logName, ((XElement)a).Value);
                                if (a != null)
                                {
                                    sbContent.Append(string.Format("ErrCode:{0} Message:{1} ", item.Value, ((XElement)a).Value));
                                }
                                
                            }
                        }
                    }
                    LogHelper.WriteWarningLogExt(logName, "输出[重新发布]工单到 {0}", xmlOutPath);
                    //输出发布工单文件到指定位置
                    //rootNode.Save(outXmlPath);
                    //using (StreamWriter xmlWriter = new StreamWriter(xmlOutPath, false, new UTF8Encoding(false)))
                    //{
                    //    rootNode.Save(xmlWriter);
                    //}

                    //rootNode.Save(outXmlPath);
                    //使用XmlTextWriter会出现生成XML空元素/空节点自动换行，导致有些程序解析出现问题
                    //XmlTextWriter xmlWriter = new XmlTextWriter(outXmlPath, Encoding.UTF8);  new UTF8Encoding(false)

                    XmlWriterSettings settings = new XmlWriterSettings();
                    settings.Encoding = new UTF8Encoding(false);
                    settings.NewLineChars = Environment.NewLine;
                    settings.Indent = true;
                    using (XmlWriter xmlWriter = XmlWriter.Create(xmlOutPath, settings))
                    {
                        rootNode.WriteTo(xmlWriter);
                        //rootNode.Save(xmlWriter);
                    }
                    //XmlTextWriter xmlWriter = new XmlTextWriter(outXmlPath, new UTF8Encoding(false));
                    //rootNode.Save(xmlWriter);
                    //xmlWriter.Close();

                    return rootNode.ToString();
                }
                else
                {
                    throw new RunException(RunCode.FileNotFound, "");
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteErrorLogExt(logName, ex.Message);
                return "";
            }
        }

        /// <summary>
        /// 解析回单内容
        /// </summary>
        /// <param name="myParams"></param>
        /// <returns></returns>
        //public WorkOutMessage ReadC2BackXml(C2InParamsDto myParams)
        //{
        //    try
        //    {
        //        LogHelper.WriteInfoLogEx(myParams.CorrelateID, string.Format("CDN出库回馈工单开始解析：{0}", myParams.ResFile.ResourcSaveAddr));
        //        //XDocument rootNode = XDocument.Load("D:\\Work\\IPTV\\DEV\\WCU\\C2BackXml.xml");
        //        XDocument rootNode = XDocument.Load(myParams.ResFile.ResourcSaveAddr);
        //        XElement rootElement = rootNode.Root;
        //        myParams.BackContent = rootNode.ToString();
        //        PublishDBHelper.GetInstance().UpdatePubBackMsg(myParams.CorrelateID, EnumC2Stat.PublishEnd, myParams.BackContent);
        //        WorkOutMessage rtnMsg = new WorkOutMessage { Code = -1, Message = "回馈工单解析错误！" };
        //        //新版CIMP回执文件对每个异常节点进行了单独处理，需进行解析并读取 2024-11-11 Hansy
        //        /*
        //         * <Object ElementType="Cast" Action="UPDATE" Code="10006076de75931b4546c8f12">
        //         *      <Property Name="Result">-1</Property>
        //         *      <Property Name="ErrorDescription">关联内容不存在:Series[10006076202410190103] not exist;审核状态:not need</Property>
        //         * </Object>
        //         * 
        //         * */
        //        //foreach (XElement item in rootElement.Elements())
        //        //{
        //        //    if (item.HasElements)
        //        //    {

        //        //    }
        //        //}

        //        if (rootElement != null && rootElement.Element("Reply") != null)
        //        {
        //            XElement oElement = rootElement.Element("Reply");
        //            if (oElement.HasElements)
        //            {

        //                foreach (var item in oElement.Elements())
        //                {
        //                    if (item.Attribute("Name").Value == "Description")
        //                    {
        //                        rtnMsg.Message = item.Value;
        //                    }
        //                }
        //            }
        //        }
        //        LogHelper.WriteInfoLogEx(myParams.CorrelateID, string.Format("CDN出库回馈工单错误信息：{0}", rtnMsg.Message));
        //        return rtnMsg;
        //    }
        //    catch (Exception ex)
        //    {
        //        LogHelper.WriteInfoLogEx(myParams.CorrelateID, ex.Message);
        //        return new WorkOutMessage { Code = -1, Message = ex.Message };
        //    }
        //}

        private void PrintMoveNodeMsg(XDocument rootNode, string logName)
        {
            //提取所有视频节点
            var movieNodes = from myTarget in rootNode.Descendants("Object")
                             where myTarget.Attribute("ElementType").Value.Equals("Movie")
                             select myTarget;
            if (movieNodes.Any())
            {
                foreach (var item in movieNodes)
                {
                    foreach (var itema in item.Elements())
                    {
                        //修改FileURL值
                        if (itema.Attribute("Name").Value.ToLower().Equals("fileurl"))
                        {
                            LogHelper.WriteWarningLogExt(logName, string.Format("输出发布工单中的介质下载地址为 {0}", itema.Value));
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 重写发布工单
        /// </summary>
        /// <param name="logName">工单流水号做日志名称</param>
        /// <param name="MediaInjectConfig">注入配置信息</param>
        /// <param name="inXmlPath">注入工单全路径</param>
        /// <param name="outXmlPath">发布工单全路径</param>
        /// <returns>发布工单新地址</returns>
        //public string RewritePubXml(string logName, MediaInjectConfig injectConfig, string inXmlPath, string outXmlPath)
        //{
        //    //介质下载完整路径 ftp://zzxxotttelecom:WedoiPtv_8500@172.25.8.117:21/Movie/mzc002002s2ark5/y4100akbp3q.2.y4100akbp3q.321004/y4100akbp3q.2.y4100akbp3q.321004.ts.m3u8
        //    //ftp://zzx_tencent_tar:zzx123456@182.138.25.61/mzc00200rh9pv6b/e0040q1y2dv.2.d0040tay2fx.321004.tar
        //    //ftp://zftp:zftp@182.131.0.201:21/bilibili/iptvsdkmdium/45574/1271956688/_00002ilhk33pr1vpr2olenbvxytj1hb-drm_slice.zip
        //    //PubSite ftp://tysxtelecom:wEdoIptv_8255@172.25.8.117:21/
        //    string pubContent = string.Empty;
        //    if (File.Exists(inXmlPath))
        //    {
        //        XDocument rootNode = XDocument.Load(inXmlPath); //XDocument.Load("D:\\Temp\\xml\\sync_newC2_content_0a7cb6da-cb55-4a15-9a21-fd2c88f334d9.xml");
        //        //XElement rootElement = rootNode.Root;
        //        //提取所有图片节点
        //        var mediaNodes = from myTarget in rootNode.Descendants("Object")
        //                         where myTarget.Attribute("ElementType").Value.Equals("Picture") || myTarget.Attribute("ElementType").Value.Equals("Movie")
        //                         select myTarget;
        //        if (mediaNodes.Any())
        //        {
        //            foreach (var item in mediaNodes)
        //            {
        //                foreach (var itemsub in item.Elements())
        //                {
        //                    //修改FileURL值
        //                    if (itemsub.Attribute("Name").Value.ToLower().Equals("fileurl"))
        //                    {
        //                        //重试发布（新工单）应使用原始日期，而不是当前日期，介质下载是在原始时间点的目录下
        //                        string pubUrl = GetTruePubUrl(injectConfig, itemsub.Value, logName);
        //                        itemsub.Value = pubUrl;
        //                        pubContent = pubUrl;
        //                        if (string.IsNullOrEmpty(pubUrl))
        //                        {
        //                            LogHelper.WriteWarningLogExt(logName, "介质下载地址获取失败");
        //                            break;
        //                        }
        //                        LogHelper.WriteWarningLogExt(logName, string.Format("输出发布工单中的介质下载地址为 {0}", itemsub.Value));
        //                    }
        //                }
        //            }

        //            if (!string.IsNullOrEmpty(pubContent))
        //            {
        //                LogHelper.WriteWarningLogExt(logName, "输出[重新发布]工单到 {0}", outXmlPath);
        //                //输出发布工单文件到指定位置
        //                //rootNode.Save(outXmlPath);
        //                StreamWriter xmlWriter = new StreamWriter(outXmlPath, false, new UTF8Encoding(false));
        //                rootNode.Save(xmlWriter);
        //                xmlWriter.Close();

        //                //rootNode.Save(outXmlPath);
        //                //XmlTextWriter xmlWriter = new XmlTextWriter(outXmlPath, Encoding.UTF8); 
        //                //using (XmlTextWriter xmlWriter = new XmlTextWriter(outXmlPath, new UTF8Encoding(false)))
        //                //{
        //                //    rootNode.Save(xmlWriter);
        //                //}
        //                //XmlTextWriter xmlWriter = new XmlTextWriter(outXmlPath, new UTF8Encoding(false));
        //                //rootNode.Save(xmlWriter);
        //                //xmlWriter.Close();
        //            }
        //            else
        //            {
        //                throw new RunException(RunCode.FileNotFound, "");
        //            }
        //        }
        //        else
        //        {
        //            LogHelper.WriteWarningLogExt(logName, "未找到介质下载节点，当前工单{0}不进行重写", outXmlPath);
        //        }
        //    }
        //    else
        //    {
        //        LogHelper.WriteErrorLogExt(logName, "注入工单文件地址{0}错误", inXmlPath);
        //    }
        //    return pubContent;
        //}

        /// <summary>
        /// 获取真实的介质发布地址 PUB-FTP地址
        /// </summary>
        /// <param name="injectConfig">注入配置信息</param>
        /// <param name="mediaUrl">注入的FTP地址</param>
        /// <param name="tmplogName">日志名称</param>
        /// <returns>发布地址</returns>
        //private string GetTruePubUrl(MediaInjectConfig injectConfig, string mediaUrl, string tmplogName)
        //{
        //    //LogHelper.WriteDebugLogExt(tmplogName, "校验媒体文件{0}是否存在", mediaUrl);
        //    string pubUrl = string.Empty;
        //    //判断使用源路径还是使用本地日期路径 M3U8文件需要使用源路径，否则TS切片文件可能会重名，导致文件冲突
        //    var siteInfo = FtpUrlParser.ParseFtpUrl(mediaUrl);
        //    if (siteInfo != null && siteInfo.FileSets != null && siteInfo.FileSets.Count > 0)
        //    {
        //        SiteFileStruct ftpfile = siteInfo.FileSets[0];
        //        LogHelper.WriteWarningLogExt(tmplogName, "源文件：{0} 后缀名为 {1} {2} {3}", mediaUrl, ftpfile.ResExtName, injectConfig.PubDateStr, injectConfig.PubDate);

        //        //根据模板获取输出的文件名
        //        string outfileName = !string.IsNullOrEmpty(injectConfig.FileNameTemplate) && ftpfile.ResType == 0 ? injectConfig.FileNameTemplate.Replace("{fName}", ftpfile.Name) : ftpfile.FileName;
        //        string pubPath = ftpfile.FileName;
        //        if (injectConfig.AllowSourcePath && ftpfile.ResType < 3)
        //        {
        //            LogHelper.WriteWarningLogExt(tmplogName, "在{0}中提取 {1}级目录", ftpfile.RemoteFileName, injectConfig.SorucePathLevel);
        //            //提取指定数量的源目录做流文件主目录
        //            string prePath = GetLastLevelDirectory(ftpfile.RemoteFileName, injectConfig.SorucePathLevel);
        //            pubPath = string.Concat(prePath, "/", outfileName);
        //            LogHelper.WriteWarningLogExt(tmplogName, string.Format("当前工单使用源地址{0} 作为发布工单介质下载地址 {1} {2}", pubPath, ftpfile.ResType, injectConfig.AllowSourcePath));
        //            //修改文件扩展名，用于输出目录判断
        //            ftpfile.ResExtName = Path.GetExtension(pubPath);
        //        }

        //        string outFileFullPath = Path.Combine(injectConfig.SaveRootPath, ftpfile.ResTypeStr, injectConfig.PubDateStr.Replace("/", "\\"), pubPath);
        //        //检查文件是否存在
        //        if (injectConfig.IsFileExists)
        //        {
        //            LogHelper.WriteWarningLogExt(tmplogName, "校验媒体文件{0}是否存在", outFileFullPath);
        //            //主要目的是为了获取文件的真实目录，原因是跨日问题导致的存储路径与数据库中记录路径不一致
        //            if (!File.Exists(outFileFullPath.Replace("/", "\\")))
        //            {
        //                LogHelper.WriteErrorLogExt(tmplogName, "未找到文件{0}", outFileFullPath);
        //                //在上一天或下一天的目录中查找文件
        //                string tmpDateStr = injectConfig.PubDate.AddDays(-1).ToString("yyyyMM/dd");
        //                outFileFullPath = Path.Combine(injectConfig.SaveRootPath, ftpfile.ResTypeStr, tmpDateStr, pubPath);
        //                if (!File.Exists(outFileFullPath.Replace("/", "\\")))
        //                {
        //                    LogHelper.WriteErrorLogExt(tmplogName, "未找到文件{0}", outFileFullPath.Replace("/", "\\"));
        //                    tmpDateStr = injectConfig.PubDate.AddDays(1).ToString("yyyyMM/dd");
        //                    outFileFullPath = Path.Combine(injectConfig.SaveRootPath, ftpfile.ResTypeStr, tmpDateStr, pubPath);
        //                    if (!File.Exists(outFileFullPath.Replace("/", "\\")))
        //                    {
        //                        LogHelper.WriteErrorLogExt(tmplogName, "未找到文件{0}", outFileFullPath.Replace("/", "\\"));
        //                        return string.Empty;
        //                    }
        //                    else
        //                    {
        //                        pubUrl = string.Concat(injectConfig.MediaPubUrl, ftpfile.ResTypeStr, "/", tmpDateStr, "/", pubPath);
        //                    }
        //                }
        //                else
        //                {
        //                    pubUrl = string.Concat(injectConfig.MediaPubUrl, ftpfile.ResTypeStr, "/", tmpDateStr, "/", pubPath);
        //                }
        //            }
        //            else
        //            {
        //                pubUrl = string.Concat(injectConfig.MediaPubUrl, ftpfile.ResTypeStr, "/", injectConfig.PubDateStr, "/", pubPath);
        //            }
        //        }
        //        else
        //        {
        //            LogHelper.WriteWarningLogExt(tmplogName, "不校验媒体文件{0}存在性", outFileFullPath);
        //            pubUrl = string.Concat(injectConfig.MediaPubUrl, ftpfile.ResTypeStr, "/", injectConfig.PubDateStr, "/", pubPath);
        //            //Path.Combine(injectConfig.MediaPubUrl, ftpfile.ResTypeStr, injectConfig.PubDateStr, pubPath);
        //        }
        //    }
        //    return pubUrl;
        //}

        /// <summary>
        /// 根据输入值获取指定数量的目录
        /// </summary>
        /// <param name="srcDir">目录全路径</param>
        /// <param name="index">取值索引</param>
        /// <returns></returns>
        private string GetLastLevelDirectory(string srcDir, int index = 0)
        {
            //入参样例 腾讯 mzc00200rr1npmb/w0045tdsi7y.2.w0045tdsi7y.321004.tar  mzc00200rr1npmb/w0045tdsi7y.2.w0045tdsi7y.321004/w0045tdsi7y.2.w0045tdsi7y.321004.ts.m3u8
            //入参样例 B站 bilibili/iptvsdkmdium/48608/27139378014/_000028h2ygeqva84826pcep7zecrw4b-drm_slice.zip 27139378014/_000028h2ygeqva84826pcep7zecrw4b-drm_slice/video.m3u8
            //入参样例 爱奇艺 media/100/825719/442626/0100/8257194426260100/8eb7e3a69b8411efbfd7ae2d52de9f4e/8257194426260100.tar 8eb7e3a69b8411efbfd7ae2d52de9f4e/8257194426260100.m3u8
            string tmpDir = string.Empty;
            if (string.IsNullOrEmpty(srcDir))
            {
                return "";
            }

            string fileName = Path.GetFileNameWithoutExtension(srcDir);
            string[] dirs = srcDir.Split('/');
            if (dirs.Length < index) index = 0;
            if (index != 0)
            {
                switch (index)
                {
                    case -1:  //取最后一级目录和文件名（不含后缀）做目录
                        tmpDir = string.Concat(dirs[dirs.Length - 2], "/", fileName);
                        break;
                    default: //默认取最后一级目录
                        tmpDir = dirs[dirs.Length - 2];
                        break;
                }
            }

            return tmpDir;
        }

        /// <summary>
        /// 查找媒体文件，并输出正确的全路径
        /// </summary>
        /// 
        /// <remarks>检索文件，并输出正确的路径</remarks>
        private void FindMedia(string savePath, string dateStr, string fileName)
        {

        }
        #endregion 内容工单处理
    }
}
